/**
  ****************************(C) COPYRIGHT 2019 DJI****************************
  * @file       can_receive.c/h
  * @brief      there is CAN interrupt function  to receive motor data,
  *             and CAN send function to send motor current to control motor.
  *             这里是CAN中断接收函数，接收电机数据,CAN发送函数发送电机电流控制电机.
  * @note       
  * @history
  *  Version    Date            Author          Modification
  *  V1.0.0     Dec-26-2018     RM              1. done
  *  V1.1.0     Nov-11-2019     RM              1. support hal lib
  *
  @verbatim
  ==============================================================================

  ==============================================================================
  @endverbatim
  ****************************(C) COPYRIGHT 2019 DJI****************************
  */

#ifndef CAN_RECEIVE_H
#define CAN_RECEIVE_H

#include "struct_typedef.h"
#include "robot_config.h"
#include "debug_config.h"

//rm motor data
typedef struct
{
    uint16_t ecd;
    int16_t speed_rpm;
    int16_t given_current;
    uint8_t temperate;
} motor_measure_t;


#ifdef SENTRY
#define CHASSIS_GIMBAL_CAN hcan1
#define CHASSIS_CAN hcan2
#define GIMBAL_CAN hcan2

//上云台发送的数据结构体
typedef struct
{
    int8_t x;		//[-127,127]线性映射
    int8_t y;		//
    int8_t w;		//
    int8_t nextmode; //下一个模式
    int16_t yawAngle;//C
}betweenTwoSTM_t;

#ifdef SENTRY_GIMBAL
typedef struct 
{
    uint16_t heatLimte;
    uint16_t heat;
}power_and_heat_t;

#endif

typedef enum
{
    CAN_FROM_NUC=0x005, //can1 NUC数据
    CAN_HEAT_AND_POWER=0x001,
    #ifdef SENTRY_CHASSIS
    CAN_G_STM_CAN1_ID = 0x2FF, 
    
    CAN_CHASSIS_M_CAN2_ID = 0x200, //表示底盘上M3508在CAN2上的标识符
    CAN_CHASSIS_LF_M = 0x201,
    CAN_CHASSIS_RF_M = 0x202,
    CAN_CHASSIS_RB_M = 0x203,
    CAN_CHASSIS_LB_M = 0x204,

    CAN_CHASSIS_G_CAN1_ID = 0x1FF, //底盘GM6020
    CAN_CHASSIS_LF_G = 0x205,
    CAN_CHASSIS_RF_G = 0x206,
    CAN_CHASSIS_RB_G = 0x207,
    CAN_CHASSIS_LB_G = 0x208,

    CAN_YAW_DOWN = 0x209,
    #endif
    #ifdef SENTRY_GIMBAL
    CAN_M_CAN1_ID=0x1FF,
    CAN_SHOOT_UP_TRIGGER=0x207,

    CAN_G_STM_CAN1_ID = 0x2FF,  
    CAN_YAW_DOWN = 0x209, 

    CAN_G_CAN2_ID=0x2FF,
    CAN_YAW_UP = 0x209,
    CAN_PITCH_DOWN = 0x20A,
    CAN_PITCH_UP = 0x20B,

    CAN_M_UP_CAN2_ID = 0x200, 
    CAN_SHOOT_UP_FRIC_L = 0x202,
    CAN_SHOOT_UP_FRIC_R = 0x203,
    CAN_SHOOT_DOWN_TRIGGER = 0x204,

    CAN_M_DOWN_CAN2_ID = 0x1FF, 
    CAN_SHOOT_DOWN_FRIC_L = 0x207,
    CAN_SHOOT_DOWN_FRIC_R = 0x208,
    
    #endif
} can_msg_id_e;

typedef enum
{
    #ifdef SENTRY_GIMBAL
    YAW_UP,
    PITCH_UP,
    SHOOT_UP_FRIC_L,
    SHOOT_UP_FRIC_R,
    SHOOT_UP_TRIGGER,
    YAW_DOWN,
    PITCH_DOWN,
    SHOOT_DOWN_FRIC_L,
    SHOOT_DOWN_FRIC_R,
    SHOOT_DOWN_TRIGGER,
    #endif
    #ifdef SENTRY_CHASSIS
    CHASSIS_LF_M,         //M3508
    CHASSIS_RF_M,
    CHASSIS_RB_M,
    CHASSIS_LB_M,
    CHASSIS_LF_G,          //GM6020
    CHASSIS_RF_G,
    CHASSIS_RB_G,
    CHASSIS_LB_G,
    YAW_DOWN,   
    #endif        
    LENGTH_OF_MOTOR_ID,
    
} motor_virtual_ID;

#ifdef SENTRY_CHASSIS
void CAN_cmd_chassis_M3508(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4);
void CAN_cmd_chassis_GM6020(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4);
extern betweenTwoSTM_t *get_between_two_STM_message_point(void);
#else
void CAN_cmd_shoot_up_stm(int16_t shootUp);
void CAN_cmd_yaw_down(int16_t yawDown);
void CAN_cmd_GIMBAL_CAN_G(int16_t yawUp, int16_t pitchDown, int16_t pitchUp);
void CAN_cmd_GIMBAL_CAN_M_up(int16_t shootUpFricL, int16_t shootUpFricR, int16_t triggerDown);
void CAN_cmd_GIMBAL_CAN_M_down(int16_t shootDownFricL, int16_t shootDownFricR);
extern betweenTwoSTM_t *get_between_two_STM_message_point(void);
uint8_t get_shoot_heat_limit(void);
uint8_t get_shoot_heat_1(void);
#endif

#else
#define CHASSIS_CAN hcan1
#define GIMBAL_CAN hcan2
#define SHOOT_CAN hcan2
/* CAN send and receive ID */
typedef enum
{
    CAN_FROM_NUC=0x005, //can1 NUC数据

    CAN_CHASSIS_ALL_ID = 0x200, //can1
    CAN_3508_M1_ID = 0x201,
    CAN_3508_M2_ID = 0x202,
    CAN_3508_M3_ID = 0x203,
    CAN_3508_M4_ID = 0x204,

    CAN_YAW_CAN1_ID = 0x1FF, //can1
    CAN_YAW_MOTOR_ID = 0x205,

    CAN_GIMBAL_ALL_ID = 0x1FF, //can2
    CAN_PIT_MOTOR_ID = 0x206,
    CAN_TRIGGER_MOTOR_ID = 0x207,

    CAN_SHOOT_ALL_ID=0X200, //can2
    CAN_SHOOT_3508_ID_1=0X201,
    CAN_SHOOT_3508_ID_2=0X202,

} can_msg_id_e;

typedef enum
{
    CHASSIS_LF_M,         //M3508
    CHASSIS_RF_M,
    CHASSIS_RB_M,
    CHASSIS_LB_M,
    YAW_GM,
    PITCH_GM,
    SHOOT_TRIGGER, 
    SHOOT_FRIC_L,
    SHOOT_FRIC_R,       
    LENGTH_OF_MOTOR_ID,
    
} motor_virtual_ID;

extern void CAN_cmd_gimbal(int16_t pitch, int16_t shoot);
extern void CAN_cmd_yaw(int16_t yaw);
extern void CAN_cmd_chassis(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4);
extern void CAN_cmd_shoot(int16_t motor5, int16_t motor6);
#endif
const motor_measure_t *get_motor_measure_point(uint8_t i);

#ifdef USE_CAN
#define NUC_DATA_AVAILABLE 1
#define NUC_DATA_NOT_AVAILABLE 0


typedef struct {
    int8_t x;
    int8_t y;
    int8_t w;
    int16_t yaw;
    int8_t pitch;
    int8_t yawWithoutIMU;
    int8_t pitchWithoutIMU;
    uint8_t shoot;
    uint8_t shootUp;
} fromNUC_t;

typedef struct
{
    uint32_t start;                 // 开始符号，'S'
    uint32_t blood : 12;            // 剩余血量，不会高于4096
    uint32_t bullet_remaining : 12; // 剩余子弹，不会高于4096
    uint32_t my_color : 8;          // 本方颜色，32bit对齐
    uint32_t checksum;              // 校验和，前方所有数据按32bit分段直接相加
    uint32_t end;                   // 结束符号，'E'
}toNUC_t;

enum myColor_e {
    COLOR_RED = 0,
    COLOR_BLUE = 1,
};

const fromNUC_t *get_nuc_control_point(void);
int found_armor(void);
int found_armorUp(void);
void gimbal_clear_read_mark(void);
void gimbal_set_read_mark(void);
int gimbal_NUC_is_available(void);
int shoot_NUC_is_available(void);
void shoot_clear_read_mark(void);
void shoot_set_read_mark(void);
void to_nuc_send_task(void const *pvParameters);
#endif
#ifdef OLED_CAN_RECEIVE
void oled_can_receive(void);
#endif
#endif
